package com.yc.tank;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import com.yc.tank.util.PropertiesTools;

public class TankFrame extends Frame {
	
	public final int GAME_WIDTH = PropertiesTools.getInt("gameWidth");
	public final int GAME_HEIGTH = PropertiesTools.getInt("gameHeigth");
	Tank myTank = new Tank(PropertiesTools.getInt("myTankeInitWidth"), 
			PropertiesTools.getInt("myTankeInitHeigth"), Group.GOOD, false, this);
	List<Tank> tanks = new ArrayList<>();
	List<Bullet> bullets = new ArrayList<>();
	List<Explode> explodes = new ArrayList<>();

	public TankFrame() throws HeadlessException {
		setSize(GAME_WIDTH, GAME_HEIGTH);
		setResizable(false);
		setTitle("Tank war");
		setVisible(true);
		
		addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
			
		});
		
		addKeyListener(new MyKeyListener());
		
		//加载6个地方坦克
		int badTankSize = PropertiesTools.getInt("badTankSize");
		for (int i = 0; i < badTankSize; i++) {
			tanks.add(new Tank(90 * (i + 1), 150, Group.BAD, true, this));
		}
		
	}
	
	

	/**
	 * 绘制游戏舞台
	 */
	@Override
	public void paint(Graphics g) {
		//在屏幕画出战场上拥有的子弹数量
		g.setColor(Color.WHITE);
		g.drawString("子弹数量:" + bullets.size(), 10, 50);
		g.drawString("敌方坦克数量:" + tanks.size(), 10, 80);
		g.drawString("爆破数量:" + explodes.size(), 10, 100);
		
		//绘制我方坦克
		myTank.paint(g);
		
		//绘制敌方坦克
		for (int i = 0; i < tanks.size(); i++) {
			tanks.get(i).paint(g);
		}
		
		//绘制子弹
		for (int i = 0; i < bullets.size(); i++) {
			bullets.get(i).paint(g);
		}
		
		//笛卡尔积检测所有子弹和所有地方坦克的碰撞
		for (int i = 0; i < tanks.size(); i++) {
			for (int j = 0; j < bullets.size(); j++) {
				collide(tanks.get(i), bullets.get(j));
			}
		}
		
		//绘制爆炸
		for (int i = 0; i < explodes.size(); i++) {
			explodes.get(i).paint(g);
		}
		//销毁爆破（之所以在这里销毁，因为前面在用list，如果用的过程中删除，会出问题）
		for (int i = 0; i < explodes.size(); i++) {
			explodes.get(i).die();
		}
		
	}
	
	Image offScreenImage = null;
	/**
	 * 消除闪烁
	 * 解决计算速度跟不上屏幕刷新速度的问题：直接在内存计算完之后，一次性加载到屏幕
	 */
	@Override
	public void update(Graphics g) {
		if (offScreenImage == null) {
			offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGTH);
		}
		Graphics gOffScreen = offScreenImage.getGraphics();
		gOffScreen.setColor(Color.BLACK);
		gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGTH);
		paint(gOffScreen);//
		g.drawImage(offScreenImage, 0, 0, null);
	}

	/**
	 * 碰撞检测
	 * @param tank
	 * @param bullet
	 */
	private void collide(Tank tank, Bullet bullet) {
		if (tank.getGroup().equals(bullet.getGroup()))
			return;//如果是同一个团队的，不做碰撞检查
		if (tank.getRect().intersects(bullet.getRect())) {
			tank.die();
			bullet.die();
		}
	}


	/**
	 * 预测：按下去变方向，弹起来该方向又停，
	 * 那么效果就是：只有键盘按着才会走
	 * @author Administrator
	 *
	 */
	class MyKeyListener extends KeyAdapter {
		
		boolean bL = false;
		boolean bU = false;
		boolean bR = false;
		boolean bD = false;
		

		@Override
		public void keyPressed(KeyEvent e) {
			int key = e.getKeyCode();
			switch (key) {
			case KeyEvent.VK_LEFT:
				bL = true;
				break;
			case KeyEvent.VK_UP:
				bU = true;
				break;
			case KeyEvent.VK_RIGHT:
				bR = true;
				break;
			case KeyEvent.VK_DOWN:
				bD = true;
				break;
			default :
					break;
			}
			
			changeDir();
		}
		
		/**
		 * 之所以加上按键弹起的事件，就是为了为了达到：键盘不按就停止的效果
		 * 所谓按键不按就停止就是：弹起的时候再触发一个事件：把坦克停下来（相当于重置方向）
		 * 还有一种方案：按一下走一格。但这种方案会影响到整体的逻辑：用速度刷新位置
		 * 那么此时就要改为 ：每次操作都是在用位置+速度，这比较“反物理常识”，和现实世界“脱轨”，
		 * 实际世界中是不存在，你点一下前进，就瞬间前进“一单位速度的距离”这种东西的
		 * 之后除了人工操作的坦克，还会有大量的“机器坦克”，操控这些坦克最好的办法就是按照真实
		 * 世界的物理规律走
		 */
		@Override
		public void keyReleased(KeyEvent e) {
			int key = e.getKeyCode();
			switch (key) {
			case KeyEvent.VK_LEFT:
				bL = false;
				break;
			case KeyEvent.VK_UP:
				bU = false;
				break;
			case KeyEvent.VK_RIGHT:
				bR = false;
				break;
			case KeyEvent.VK_DOWN:
				bD = false;
				break;
			case KeyEvent.VK_SPACE:
				myTank.fire();//把发射子弹放在弹起按键，防止一直按着不放手
				break;  
			default :
				break;
			}
			
			changeDir();
		}

		void changeDir() {
			System.out.println("x=" + myTank.getX() + ", y=" + myTank.getY() + ",dir=" + myTank.getDir());
			if (bL || bU || bR || bD) {
				myTank.setMoving(true);
				if (bL) myTank.setDir(Dir.LIFT);
				if (bU) myTank.setDir(Dir.UP);
				if (bR) myTank.setDir(Dir.RIGHT);
				if (bD) myTank.setDir(Dir.DOWN);
			} else {
				myTank.setMoving(false);
			}
			
		}
		
		
	}
	

}
